#ifndef __MANAGER_H__
#define __MANAGER_H__

#include <map>
#include <string>
#include <sstream>

namespace RayFrame
{
  /// Base class used to manager String-Value pairs.
  template<class T>
  class DLL_DECLARE Manager
  {
  protected:
    typedef std::map<STRING, T*> MapStrData;
    typedef typename MapStrData::iterator MapStrDataIter;

    MapStrData m_data;
    bool       m_autoDelete;
    unsigned   m_crtDefaultNameIndex;
  protected:
    STRING getDefaultName()
    {
      std::stringstream ss;
      ss << "_default_" << m_crtDefaultNameIndex ++;

      return ss.str();
    };
  public:
    /** Initialize the manager
    @param autoDelete if the manager should delete the pointer
    automaticly.
    **/
    Manager(bool autoDelete = true)
    { 
      m_autoDelete = autoDelete; 
      m_crtDefaultNameIndex = 0;
    };

    /// Manager will delete all pointers while destroying.
    ~Manager()
    {
      if(m_autoDelete)
      {
        for(MapStrDataIter iter = m_data.begin();
          iter != m_data.end();
          iter++)
        {
          SAFE_DELETE(iter->second);
        }
      }

      m_data.clear();
    };

    /// Save a pointer into manager without name
    bool InsertData(T* data)
    {
      return InsertData( getDefaultName(), data );
    }

    /** Save a pointer with a specified name
    @param name the name for the data
    @param data the pointer to the data
    **/
    bool InsertData(STRING& name, T* data)
    {
      if( name.empty() )
        name = getDefaultName();

      if(m_data.find(name) != m_data.end())
        return false;

      m_data.insert(std::make_pair(name, data));
      return true;
    };

    /** Remove a data from manager. The pointer will also 
    be deleted.
    @param name the name for the data.
    **/
    bool RemoveData(STRING name)
    {
      MapStrDataIter iter = m_data.find(name);
      if(iter != m_data.end() && m_autoDelete)
      {
        SAFE_DELETE(iter->second);
        m_data.erase(iter);
        return true;
      }
      else
        return false;
    };

    /** Check if the manager have specified data
    @param data pointer to the data
    **/
    bool HaveData(T* data)
    {
      for(MapStrDataIter iter = m_data.begin();
        iter != m_data.end();
        iter++)
      {
        if( iter->second == data )
          return true;
      }
      return false;
    };

    /** Search if manager have a data with specified name.
    @param name the name of the data.
    **/
    T* SearchName(STRING name)
    {
      MapStrDataIter iter = m_data.find(name);
      if(iter != m_data.end())
        return iter->second;
      else
        return NULL;
    }

    /// Get the number of data stored in manager
    unsigned GetCount()
    {
      return m_data.count();
    };
  };
};


#endif
